import {Database} from 'better-sqlite3';
import {TransactionOptions} from "./types";

/**
 * 事务管理类
 * 专注于事务控制功能，包括开启、提交、回滚和保存点操作
 */
export class Transaction {
  // 事务嵌套计数
  private nestLevel: number = 0;

  // 事务回滚标志
  private rolledBack: boolean = false;

  // 当前活动事务
  private activeTransaction: boolean = false;

  /**
   * 构造函数
   * @param db 数据库连接实例
   * @param debug 是否启用调试模式
   */
  constructor(
    private db: Database,
    private debug: boolean = false
  ) {
  }

  /**
   * 开始一个新事务
   * 支持嵌套事务和不同的事务隔离级别
   *
   * @param options 事务选项
   * @returns 当前事务实例，支持链式调用
   */
  public begin(options?: TransactionOptions): Transaction {
    const isolationLevel = options?.isolationLevel || 'DEFERRED';

    // 如果已经在事务中，递增嵌套计数
    if (this.activeTransaction) {
      this.nestLevel++;
      return this;
    }

    // 重置事务状态
    this.rolledBack = false;
    this.nestLevel = 1;

    // 开始事务并设置隔离级别
    if (isolationLevel === 'READ UNCOMMITTED' || isolationLevel === 'READ COMMITTED' || isolationLevel === 'SERIALIZABLE') {
      // SQLite PRAGMA for transaction isolation
      this.db.prepare(`PRAGMA transaction_mode=${isolationLevel}`).run();
      this.db.prepare('BEGIN TRANSACTION').run();
    } else {
      // 直接使用SQLite的事务模式
      this.db.prepare(`BEGIN ${isolationLevel} TRANSACTION`).run();
    }

    this.activeTransaction = true;
    if (this.debug) {
      console.log(`Transaction started with isolation level: ${isolationLevel}`);
    }

    return this;
  }

  /**
   * 提交事务
   * 对于嵌套事务，只有最外层事务会实际执行提交操作
   *
   * @returns 当前事务实例，支持链式调用
   */
  public commit(): Transaction {
    if (!this.activeTransaction) {
      throw new Error('No active transaction to commit');
    }

    // 如果已回滚，不执行提交
    if (this.rolledBack) {
      if (this.debug) {
        console.log('Transaction already rolled back, commit ignored');
      }
      return this;
    }

    // 如果是最外层事务，则实际执行提交
    if (this.nestLevel === 1) {
      this.db.prepare('COMMIT').run();
      this.activeTransaction = false;
      this.nestLevel = 0;

      if (this.debug) {
        console.log('Transaction committed');
      }
    } else {
      // 嵌套事务，仅减少计数
      this.nestLevel--;
      if (this.debug) {
        console.log(`Nested transaction committed, current level: ${this.nestLevel}`);
      }
    }

    return this;
  }

  /**
   * 回滚事务
   * 标记整个事务链需要回滚
   *
   * @returns 当前事务实例，支持链式调用
   */
  public rollback(): Transaction {
    if (!this.activeTransaction) {
      throw new Error('No active transaction to rollback');
    }

    // 如果是最外层事务，则实际执行回滚
    if (this.nestLevel === 1) {
      if (this.db.inTransaction) {
        this.db.prepare('ROLLBACK').run();
      }

      this.activeTransaction = false;
      this.nestLevel = 0;
      this.rolledBack = false;

      if (this.debug) {
        console.log('Transaction rolled back');
      }
    } else {
      // 嵌套事务，标记回滚并减少计数
      this.rolledBack = true;
      this.nestLevel--;

      if (this.debug) {
        console.log(`Nested transaction marked for rollback, current level: ${this.nestLevel}`);
      }
    }

    return this;
  }

  /**
   * 创建保存点
   * 在复杂事务中创建可回滚点
   *
   * @param name 保存点名称
   * @returns 当前事务实例，支持链式调用
   */
  public savepoint(name: string): Transaction {
    if (!this.activeTransaction) {
      throw new Error('No active transaction for savepoint creation');
    }

    this.db.prepare(`SAVEPOINT ${name}`).run();

    if (this.debug) {
      console.log(`Savepoint created: ${name}`);
    }

    return this;
  }

  /**
   * 回滚到指定保存点
   *
   * @param name 保存点名称
   * @returns 当前事务实例，支持链式调用
   */
  public rollbackTo(name: string): Transaction {
    if (!this.activeTransaction) {
      throw new Error('No active transaction for savepoint rollback');
    }

    this.db.prepare(`ROLLBACK TO SAVEPOINT ${name}`).run();

    if (this.debug) {
      console.log(`Rolled back to savepoint: ${name}`);
    }

    return this;
  }

  /**
   * 释放保存点
   *
   * @param name 保存点名称
   * @returns 当前事务实例，支持链式调用
   */
  public releaseSavepoint(name: string): Transaction {
    if (!this.activeTransaction) {
      throw new Error('No active transaction for savepoint release');
    }

    this.db.prepare(`RELEASE SAVEPOINT ${name}`).run();

    if (this.debug) {
      console.log(`Released savepoint: ${name}`);
    }

    return this;
  }

  /**
   * 在事务中执行指定函数
   * 如果函数成功执行，则提交事务；如果发生异常，则回滚事务
   *
   * @param func 在事务中执行的函数
   * @param options 事务选项
   * @returns 函数的返回值
   */
  public run<T>(func: () => T, options?: TransactionOptions): T {
    const isOuterTransaction = !this.activeTransaction;

    // 开始事务(如果尚未开始)
    if (isOuterTransaction) {
      this.begin(options);
    } else {
      this.nestLevel++;
    }

    try {
      // 执行函数
      const result = func();

      // 如果是外层事务并且未标记回滚，则提交
      if (isOuterTransaction && !this.rolledBack) {
        this.commit();
      } else if (!isOuterTransaction) {
        this.nestLevel--;
      }

      return result;
    } catch (err) {
      // 回滚事务
      if (isOuterTransaction) {
        this.rollback();
      } else {
        this.rolledBack = true;
        this.nestLevel--;
      }

      if (this.debug) {
        console.error('Transaction rolled back due to error:', err);
      }

      throw err;
    }
  }

  /**
   * 获取底层数据库连接
   */
  public getDatabase(): Database {
    return this.db;
  }

  /**
   * 是否处于活动事务中
   */
  public isActive(): boolean {
    return this.activeTransaction;
  }

  /**
   * 获取当前嵌套级别
   */
  public getNestLevel(): number {
    return this.nestLevel;
  }

  /**
   * 是否已被标记为回滚
   */
  public isRolledBack(): boolean {
    return this.rolledBack;
  }
}
